/**********************************************************************

   Audacity - A Digital Audio Editor
   Copyright 1999-2018 Audacity Team
   License: wxwidgets

   James Crook

******************************************************************//**

\file DragCommand.cpp
\brief Definitions for DragCommand

\class DragCommand
\brief Command that sets clip information

*//*******************************************************************/

#include "DragCommand.h"

#include "CommandDispatch.h"
#include "MenuRegistry.h"
#include "../CommonCommandFlags.h"
#include "LoadCommands.h"
#include "Project.h"
#include "../ProjectWindows.h"
#include "WaveTrack.h"
#include "SettingsVisitor.h"
#include "ShuttleGui.h"
#include "CommandContext.h"

#include <wx/frame.h>

const ComponentInterfaceSymbol DragCommand::Symbol
{ XO("Drag") };

namespace {
BuiltinCommandsModule::Registration< DragCommand > reg;
}

DragCommand::DragCommand()
{
}

enum kCoordTypes
{
    kPanel,
    kApp,
    kTrack0,
    kTrack1,
    nCoordTypes
};

static const EnumValueSymbol kCoordTypeStrings[nCoordTypes] =
{
    { XO("Panel") },
    { wxT("App"),    XO("Application") },
    { wxT("Track0"), XO("Track 0") },
    { wxT("Track1"), XO("Track 1") },
};

template<bool Const>
bool DragCommand::VisitSettings(SettingsVisitorBase<Const>& S)
{
    S.OptionalN(bHasId).Define(mId,          wxT("Id"),         11000, -100000, 1000000);
    S.OptionalY(bHasWinName).Define(mWinName,     wxT("Window"),     wxString { "Timeline" });
    S.OptionalY(bHasFromX).Define(mFromX,       wxT("FromX"),      200.0, 0.0, 1000000.0);
    S.OptionalY(bHasFromY).Define(mFromY,       wxT("FromY"),      10.0,  0.0, 1000000.0);
    S.OptionalN(bHasToX).Define(mToX,         wxT("ToX"),        400.0, 0.0, 1000000.0);
    S.OptionalN(bHasToY).Define(mToY,         wxT("ToY"),        10.0,  0.0, 1000000.0);
    S.OptionalN(bHasRelativeTo).DefineEnum(mRelativeTo,  wxT("RelativeTo"), kPanel, kCoordTypeStrings, nCoordTypes);
    return true;
}

bool DragCommand::VisitSettings(SettingsVisitor& S)
{ return VisitSettings<false>(S); }

bool DragCommand::VisitSettings(ConstSettingsVisitor& S)
{ return VisitSettings<true>(S); }

void DragCommand::PopulateOrExchange(ShuttleGui& S)
{
    S.AddSpace(0, 5);

    S.StartMultiColumn(3, wxALIGN_CENTER);
    {
        /* i18n-hint abbreviates "Identity" or "Identifier" */
        S.Optional(bHasId).TieNumericTextBox(XXO("Id:"),          mId);
        S.Optional(bHasWinName).TieTextBox(XXO("Window Name:"), mWinName);
        S.Optional(bHasFromX).TieNumericTextBox(XXO("From X:"),      mFromX);
        S.Optional(bHasFromY).TieNumericTextBox(XXO("From Y:"),      mFromY);
        S.Optional(bHasToX).TieNumericTextBox(XXO("To X:"),        mToX);
        S.Optional(bHasToY).TieNumericTextBox(XXO("To Y:"),        mToY);
        S.Optional(bHasRelativeTo).TieChoice(XXO("Relative To:"), mRelativeTo,
                                             Msgids(kCoordTypeStrings, nCoordTypes));
    }
    S.EndMultiColumn();
}

bool DragCommand::Apply(const CommandContext& context)
{
    // Defaults if no value...
    if (!bHasFromX) {
        mFromX = 200.0;
    }
    if (!bHasFromY) {
        mFromY = 10;
    }
    if (!bHasToX) {
        mToX = 400;
    }
    if (!bHasToY) {
        mToY = 10;
    }

    wxWindow* pWin = &GetProjectFrame(context.project);
    wxWindow* pWin1 = nullptr;
    wxMouseEvent Evt(wxEVT_MOTION);
    Evt.m_x = mFromX;
    Evt.m_y = mFromY;
    if (bHasId) {
        pWin1 = pWin->FindWindowById(mId);
    }
    if (bHasWinName) {
        pWin1 = pWin->FindWindowByName(mWinName);
    }
    if (pWin1) {
        pWin = pWin1;
    }
    // Process twice - possible bug in Audacity being worked around
    // where we need an event to enter AND an event to move.
    // AdornedRuler Quick-Play bug.
    pWin->GetEventHandler()->ProcessEvent(Evt);
    pWin->GetEventHandler()->ProcessEvent(Evt);
    if (bHasToX) {
        wxMouseEvent Evt2(wxEVT_LEFT_DOWN);
        Evt2.m_leftDown = true;
        Evt2.m_x = mFromX;
        Evt2.m_y = mFromY;
        Evt2.m_aux2Down = true;
        pWin->GetEventHandler()->ProcessEvent(Evt2);
        wxMouseEvent Evt3(wxEVT_MOTION);
        Evt3.m_leftDown = true;
        Evt2.m_aux2Down = true;
        Evt3.m_x = mToX;
        Evt3.m_y = mToY;
        // AdornedRuler Quick-Play bug again.
        pWin->GetEventHandler()->ProcessEvent(Evt3);
        pWin->GetEventHandler()->ProcessEvent(Evt3);
        wxMouseEvent Evt4(wxEVT_LEFT_UP);
        Evt2.m_aux2Down = true;
        Evt4.m_x = mToX;
        Evt4.m_y = mToY;
        pWin->GetEventHandler()->ProcessEvent(Evt4);
    }
    return true;
}

namespace {
using namespace MenuRegistry;

// Register menu items

AttachedItem sAttachment{
    // Note that the PLUGIN_SYMBOL must have a space between words,
    // whereas the short-form used here must not.
    // (So if you did write "Compare Audio" for the PLUGIN_SYMBOL name, then
    // you would have to use "CompareAudio" here.)
    Command(wxT("Drag"), XXO("Move Mouse..."),
            CommandDispatch::OnAudacityCommand, AudioIONotBusyFlag()),
    wxT("Optional/Extra/Part2/Scriptables2")
};
}
